﻿using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Security;
using Newtonsoft.Json;
using Fa.Kanbox.API.Controls;

namespace Fa.Kanbox.API
{
    public class KbApiClient
    {
        private const string __TokenType = "Bearer";

        public string ClientID { get; set; }
        public string ClientSecret { get; set; }
        public KbTokenInfo TokenInfo { get; private set; }

        public KbApiClient(string clientId, string clientSecret)
        {
            this.ClientID = clientId;
            this.ClientSecret = clientSecret;
        }

        public void LoginAsync(string username, string password, GetCodeCompletedEventHandler handle)
        {
            var wbcode = new WebBrowserCode()
            {
                ClientID = ClientID,
                ClientSecret = ClientSecret,
                Username = username,
                Password = password,
                AutoLogin = true
            };
            wbcode.GetCodeCompleted += new GetCodeCompletedEventHandler((GetCodeCompletedEventArgs e) =>
            {
                if (e.Exception == null)
                {
                    this.GetToken(e.Code);
                }
                if (handle != null)
                {
                    handle(e);
                }
                wbcode.Dispose();
            });
            wbcode.ToGetCode();
        }

        public KbTokenInfo GetToken(string code)
        {
            var url = KbAddress.Token;
            var data = Encoding.UTF8.GetBytes(KbAddress.GetUrlData(new
            {
                grant_type = "authorization_code",
                client_id = ClientID,
                client_secret = ClientSecret,
                code = code,
                redirect_uri = KbAddress.RedirectUri
            }));
            using (var webct = new WebClient())
            {
                ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
                webct.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
                var bytes = webct.UploadData(url, "POST", data);
                var info = JsonConvert.DeserializeObject<KbTokenInfo>(Encoding.UTF8.GetString(bytes));
                this.TokenInfo = info;
                return this.TokenInfo;
            }
        }
         public KbTokenInfo RefreshToken(string refreshToken){
            var url = KbAddress.Token;
            var data = Encoding.UTF8.GetBytes(KbAddress.GetUrlData(new
            {
                grant_type = "refresh_token",
                client_id = ClientID,
                client_secret = ClientSecret,
                refresh_token = refreshToken
            }));
            using (var webct = new WebClient())
            {
                ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
                webct.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
                var bytes = webct.UploadData(url, "POST", data);
                var info = JsonConvert.DeserializeObject<KbTokenInfo>(Encoding.UTF8.GetString(bytes));
                this.TokenInfo = info;
                return this.TokenInfo;
            }
         }

        private void SetAppendAuthorization(WebClient webct)
        {
            webct.Headers.Add("Authorization", __TokenType + " " + this.TokenInfo.AccessToken);
        }
        private void SetAppendAuthorization(WebRequest request)
        {
            request.Headers.Add("Authorization", __TokenType + " " + this.TokenInfo.AccessToken);
        }

        public KbAccountInfo GetAccountInfo()
        {
            var url = KbAddress.Info;
            using (var webct = new WebClient())
            {
                SetAppendAuthorization(webct);
                var str = webct.DownloadString(url);
                var info = JsonConvert.DeserializeObject<KbAccountInfo>(str);
                return info;
            }
        }
        public KbListInfo GetListInfo(string path)
        {
            var url = new Uri(KbAddress.List + path);
            using (var webct = new WebClient())
            {
                SetAppendAuthorization(webct);
                var str = webct.DownloadString(url);
                var info = JsonConvert.DeserializeObject<KbListInfo>(str);
                return info;
            }
        }
        public byte[] Download(string path)
        {
            var url = new Uri(KbAddress.Download + path);
            using (var webct = new WebClient())
            {
                SetAppendAuthorization(webct);
                return webct.DownloadData(url);
            }
        }
        public void Download(string path, string savePath)
        {
            var url = new Uri(KbAddress.Download + path);
            using (var webct = new WebClient())
            {
                SetAppendAuthorization(webct);
                webct.DownloadFile(url, savePath);
            }
        }
        public void DownloadAsync(string path, string savePath,
            Action<DownloadProgressChangedEventArgs> progressAction,
            Action<AsyncCompletedEventArgs> completedAction)
        {
            var url = new Uri(KbAddress.Download + path);
            using (var webct = new WebClient())
            {
                SetAppendAuthorization(webct);
                webct.DownloadProgressChanged += new DownloadProgressChangedEventHandler((obj, args) =>
                {
                    if (progressAction != null)
                        progressAction(args);
                });
                webct.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler((obj, args) =>
                {
                    if (completedAction != null)
                        completedAction(args);
                });
                webct.DownloadFileAsync(url, savePath, webct);
            }

        }
        public void DownloadAsync(string path,
            Action<DownloadProgressChangedEventArgs> progressAction,
            Action<DownloadDataCompletedEventArgs> completedAction)
        {
            var url = new Uri(KbAddress.Download + path);
            using (var webct = new WebClient())
            {               
                SetAppendAuthorization(webct);
                webct.DownloadProgressChanged += new DownloadProgressChangedEventHandler((obj, args) =>
                {
                    if (progressAction != null)
                        progressAction(args);
                });
                webct.DownloadDataCompleted += new DownloadDataCompletedEventHandler((obj, args) =>
                {
                    if (completedAction != null)
                        completedAction(args);
                });
                webct.DownloadDataAsync(url, webct);
            }
        }
        public void UploadAsync(string targetPath,
             string sourceFilePath,
            Action<UploadProgressChangedEventArgs> progressAction,
            Action<UploadFileCompletedEventArgs> completedAction)
        {
            var url = new Uri(KbAddress.Upload + targetPath);
            using (var webct = new WebClient())
            {
                SetAppendAuthorization(webct);
                ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
                webct.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
                webct.UploadProgressChanged += new UploadProgressChangedEventHandler((obj, args) =>
                {
                    if (progressAction != null)
                        progressAction(args);
                });
                webct.UploadFileCompleted += new UploadFileCompletedEventHandler((obj, args) =>
                {
                    if (completedAction != null)
                        completedAction(args);
                });
                webct.UploadFileAsync(url, "POST", sourceFilePath, webct);
            }
        }
        public KbStatusInfo Delete(string filePath)
        {
            var url = new Uri(KbAddress.Delete + filePath);
            
            using (var webct = new WebClient())
            {
                ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
                SetAppendAuthorization(webct);
                var str = webct.DownloadString(url);
                var info = JsonConvert.DeserializeObject<KbStatusInfo>(str);
                return info;
            }
        }
        /// <summary>
        /// 移动文件或文件夹
        /// </summary>
        /// <param name="path">文件或文件夹路径</param>
        /// <param name="destinationPath">移动文件或文件夹后的目标路径</param>
        /// <returns></returns>
        public KbStatusInfo Move(string path,string destinationPath)
        {
            var url = new Uri(KbAddress.Move + path);
            using (var webct = new WebClient())
            {
                ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
                SetAppendAuthorization(webct);
                webct.QueryString["destination_path"] = destinationPath;
                var str = webct.DownloadString(url);
                var info = JsonConvert.DeserializeObject<KbStatusInfo>(str);
                return info;
            }
        }
        /// <summary>
        /// 创建新文件夹
        /// </summary>
        /// <param name="path">文件或文件夹路径</param>
        /// <returns></returns>
        public KbStatusInfo CreateFolder(string path)
        {
            var url = new Uri(KbAddress.CreateFolder + path);
            using (var webct = new WebClient())
            {
                ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
                SetAppendAuthorization(webct);
                var str = webct.DownloadString(url);
                var info = JsonConvert.DeserializeObject<KbStatusInfo>(str);
                return info;
            }
        }
        /// <summary>
        /// 创建共享
        /// </summary>
        /// <param name="path">文件或文件夹路径</param>
        /// <param name="users">请输入好友的邮箱地址或手机号码</param>
        /// <returns></returns>
        public KbShareInfo Share(string path, string[] users)
        {
            var url = new Uri(KbAddress.Share + path);
            var data = JsonConvert.SerializeObject(users);
            using (var webct = new WebClient())
            {
                ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
                SetAppendAuthorization(webct);
                var str=webct.UploadString(url, "POST", data);
                var info = JsonConvert.DeserializeObject<KbShareInfo>(str);
                return info;
            }
        }
        /// <summary>
        /// 获取共享邀请列表
        /// </summary>
        /// <returns></returns>
        public KbPendingSharesInfo GetPendingShareInfos()
        {
            var url = new Uri(KbAddress.PendingShares);
            using (var webct = new WebClient())
            {
                ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
                SetAppendAuthorization(webct);
                var str = webct.DownloadString(url);
                return JsonConvert.DeserializeObject<KbPendingSharesInfo>(str);
            }
        }
       /// <summary>
        /// 处理共享请求
       /// </summary>
       /// <param name="path">路径</param>
       /// <param name="user">用户</param>
       /// <param name="accept">是否接受</param>
       /// <returns></returns>
        public KbStatusInfo PendingShares(string path, string user, bool accept)
        {
            var url = new Uri(KbAddress.PendingShares);
            var data = JsonConvert.SerializeObject(new {
                path = path,
                user = user,
                accept = accept
            });
            using (var webct = new WebClient())
            {
                ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
                SetAppendAuthorization(webct);
                var str = webct.UploadString(url, "POST", data);
                return JsonConvert.DeserializeObject<KbStatusInfo>(str);
            }
        }
    }
}
